package top.jybill.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import top.jybill.domain.MyUser;
import top.jybill.domain.SysLog;
import top.jybill.exception.MyException;
import top.jybill.service.ISysLogService;
import top.jybill.utils.JwtUtil;
import top.jybill.utils.TokenUtils;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Component("logActive")
@Aspect
public class LogAspect {
  @Pointcut("execution(* top.jybill.service.Impl.*.*(..))")
  private void all() {

  }

  @Pointcut("execution(* top.jybill.service.Impl.ISysLogDaoServiceImpl.*(..)))")
  private void notLog() {}

  @Pointcut("!notLog() && all()")
  private void onlyNotLog() {}

  @Autowired
  private HttpServletRequest request;
  @Autowired
  private ISysLogService sysLogService;
  @Autowired
  private SysLog sysLog;
  private Class executionClass;
  private String token;
  private static final String regx = "(/user/login)|(/log/\\w+)";

  @Around("onlyNotLog()")
  public Object aroundPrintLog(ProceedingJoinPoint pjp) throws Exception {
    // 前置通知 正则匹配 拦截过滤
    boolean flag = Pattern.compile(regx).matcher(request.getRequestURI()).find();
    System.out.println("flag: " + flag);

    if (!flag) { before(pjp); }

    // 执行切入点
    Object ret;
    try {
      ret = pjp.proceed(pjp.getArgs());
    } catch (Throwable t) {
      throw new MyException(t.getMessage());
    }


    // 后置通知
    if (!flag) { after(pjp); }
    return ret;
  }

  /**
   * 前置方法
   *
   * @param pjp
   */
  private void before(ProceedingJoinPoint pjp) throws Exception {
    // 开始访问时间
    sysLog.setVisitTime(new Timestamp(System.currentTimeMillis())); // 开始时间

    // 访问的类
    executionClass = pjp.getTarget().getClass();

    // 获取token
    token = request.getHeader("Authorization").replace(JwtUtil.TOKEN_PREFIX, "");

    // 获取方法名
    sysLog.setMethod(pjp.getSignature().getName());
  }

  /**
   * 后置方法
   *
   * @param pjp
   */
  private void after(ProceedingJoinPoint pjp) {
    // 获取url
    sysLog.setUrl(request.getServletPath());

    // 获取ip
    sysLog.setIp(request.getRemoteAddr());

    // 获取访问时长
    sysLog.setExecutionTime(System.currentTimeMillis() - sysLog.getVisitTime().getTime());

    // 获取访问用户名
    sysLog.setUsername((String) TokenUtils.getMap(token, "userInfo", Map.class).get("username"));

    // 存储数据库
    sysLogService.addLog(sysLog);
  }
}
